From: Keir Fraser Date: Mon, 7 Sep 2009 12:52:17 +0000 (+0100) Subject: vt-d: don't treat IOAPIC RTE of dest_SMI type specially. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13363 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=8b4225a532d32d893f6a3cecbabedb0d551d879b;p=xen.git vt-d: don't treat IOAPIC RTE of dest_SMI type specially. We also need to create IRTE for it since we enable EIM and clear CFI, or else, the IOAPIC RTE's interrupt message would be blocked by IR unit. In io_apic_read_remap_rte(), we now use "apic_pin_2_ir_idx[apic][ioapic_pin]" rather than "(remap_rte->index_15 << 15) | remap_rte->index_0_14" to avoid the "interrupt remapping table out of bound error". Signed-off-by: Dexuan Cui --- diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c index be5ce34132..059142ec0a 100644 --- a/xen/drivers/passthrough/vtd/intremap.c +++ b/xen/drivers/passthrough/vtd/intremap.c @@ -32,7 +32,6 @@ #include "extern.h" #ifdef __ia64__ -#define dest_SMI -1 #define nr_ioapics iosapic_get_nr_iosapics() #define nr_ioapic_registers(i) iosapic_get_nr_pins(i) #else @@ -142,11 +141,9 @@ int iommu_supports_eim(void) } static int remap_entry_to_ioapic_rte( - struct iommu *iommu, struct IO_xAPIC_route_entry *old_rte) + struct iommu *iommu, int index, struct IO_xAPIC_route_entry *old_rte) { struct iremap_entry *iremap_entry = NULL, *iremap_entries; - struct IO_APIC_route_remap_entry *remap_rte; - int index = 0; unsigned long flags; struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); @@ -157,9 +154,6 @@ static int remap_entry_to_ioapic_rte( return -EFAULT; } - remap_rte = (struct IO_APIC_route_remap_entry *) old_rte; - index = (remap_rte->index_15 << 15) | remap_rte->index_0_14; - if ( index > ir_ctrl->iremap_index ) { dprintk(XENLOG_ERR VTDPREFIX, @@ -282,6 +276,8 @@ static int ioapic_rte_to_remap_entry(struct iommu *iommu, unsigned int io_apic_read_remap_rte( unsigned int apic, unsigned int reg) { + unsigned int ioapic_pin = (reg - 0x10) / 2; + int index; struct IO_xAPIC_route_entry old_rte = { 0 }; struct IO_APIC_route_remap_entry *remap_rte; int rte_upper = (reg & 1) ? 1 : 0; @@ -289,7 +285,8 @@ unsigned int io_apic_read_remap_rte( struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 || - ir_ctrl->iremap_index == -1 ) + (ir_ctrl->iremap_index == -1) || + ( (index = apic_pin_2_ir_idx[apic][ioapic_pin]) < 0 ) ) { *IO_APIC_BASE(apic) = reg; return *(IO_APIC_BASE(apic)+4); @@ -306,13 +303,7 @@ unsigned int io_apic_read_remap_rte( remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte; - if ( (remap_rte->format == 0) || (old_rte.delivery_mode == dest_SMI) ) - { - *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg; - return *(IO_APIC_BASE(apic)+4); - } - - if ( remap_entry_to_ioapic_rte(iommu, &old_rte) ) + if ( remap_entry_to_ioapic_rte(iommu, index, &old_rte) ) { *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg; return *(IO_APIC_BASE(apic)+4); @@ -353,31 +344,6 @@ void io_apic_write_remap_rte( remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte; - if ( old_rte.delivery_mode == dest_SMI ) - { - /* Some BIOS does not zero out reserve fields in IOAPIC - * RTE's. clear_IO_APIC() zeroes out all RTE's except for RTE - * with MSI delivery type. This is a problem when the host - * OS converts SMI delivery type to some other type but leaving - * the reserved field uninitialized. This can cause interrupt - * remapping table out of bound error if "format" field is 1 - * and the "index" field has a value that that is larger than - * the maximum index of interrupt remapping table. - */ - if ( remap_rte->format == 1 ) - { - remap_rte->format = 0; - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0); - *IO_APIC_BASE(apic) = reg + 1; - *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1); - } - - *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg; - *(IO_APIC_BASE(apic)+4) = value; - return; - } - /* mask the interrupt while we change the intremap table */ saved_mask = remap_rte->mask; remap_rte->mask = 1;